package com.zdb.demo.flink.streaming;

import org.apache.flink.api.common.functions.FilterFunction;
import org.apache.flink.api.common.functions.MapFunction;
import org.apache.flink.api.java.functions.KeySelector;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.configuration.Configuration;
import org.apache.flink.streaming.api.TimeCharacteristic;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.functions.timestamps.BoundedOutOfOrdernessTimestampExtractor;
import org.apache.flink.streaming.api.windowing.time.Time;
import org.apache.flink.util.OutputTag;

/**
 * 创建一个 Flink 流式作业
 *
 * 使用事件时间
 * 以事件中 timestamp 属性作为时间
 * Watermark 等于当前收到数据中最大时间减10秒
 * AllowLateness 为20秒
 * 将 SideOutput 通过 print 打印出来
 *
 *
 */
public class SideOutputDemo {

    public static void main(String[] args) throws Exception {
        Configuration conf = new Configuration(){{
            setInteger("rest.port", 9191);
            setBoolean("local.start-webserver", true);
        }};
        final StreamExecutionEnvironment streamEnv = StreamExecutionEnvironment.createLocalEnvironmentWithWebUI(conf);
        streamEnv.setParallelism(4);
        streamEnv.setStreamTimeCharacteristic(TimeCharacteristic.EventTime);

        OutputTag<Tuple2<String, Long>> outputTag = new OutputTag<Tuple2<String, Long>>("side-output") {};

        SingleOutputStreamOperator<Tuple2<String, Long>> ds = streamEnv.socketTextStream("localhost", 9999).filter(new FilterFunction<String>() {
            @Override
            public boolean filter(String value) throws Exception {
                return value!=null && value.length() > 0;
            }
        }).map(new MapFunction<String, Tuple2<String, Long>>() {
            @Override
            public Tuple2<String, Long> map(String value) throws Exception {
                String[] strs = value.split(",");
                return new Tuple2<String, Long>(strs[0], Long.parseLong(strs[1].trim()) * 1000);
            }
        }).assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor<Tuple2<String, Long>>(Time.seconds(10)) {
            @Override
            public long extractTimestamp(Tuple2<String, Long> element) {
                return element.f1;
            }
        }).keyBy(0)
                .timeWindow(Time.seconds(10)).allowedLateness(Time.seconds(20)).sideOutputLateData(outputTag)
                .max(1);

        ds.print("max------>");
        ds.getSideOutput(outputTag).print("late data---->");

        streamEnv.execute("SideOutputDemo stream job");
    }
}